﻿//if you're using .net 3.5 or later, uncomment the line below
//#define _DotNet35


#if _DotNet35

/// <summary>
/// this class is used to detect if "System.Core.dll" is referenced at compile time.
/// </summary>
static class __Dot_Net_3_5_Detection_Extensions
{
    static void _AssertIsDotNet35(this __Dot_Net_3_5_Detection obj)
    //***********if you get a compiler error here:************/
    //if you're using .net 3.5 or later : add a reference to "System.Core.dll"
    //if you're using .net 3.0 or 2.0 : modify the header of this file to tell compiler about this
    {
    }

}

/// <summary>
/// this class is used to detect if "System.Core.dll" is referenced at compile time.
/// </summary>
class __Dot_Net_3_5_Detection
{
}
#else

using System.Collections.Generic;
using System.Runtime.Serialization;

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)]
    public sealed class ExtensionAttribute : Attribute
    {
    }
}

namespace System.Linq
{
    public static class Enumerable
    {
        #region select
        /// <summary>Returns the first element of a sequence.</summary>
        /// <returns>The first element in the specified sequence.</returns>
        /// <param name="source">The <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> to return the first element of.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> is null.</exception>
        /// <exception cref="TValue:System.InvalidOperationException">The source sequence is empty.</exception>
        public static TSource First<TSource>(this IEnumerable<TSource> source)
        {
            if (source == null)
                throw new ArgumentNullException("source");

            IList<TSource> list = source as IList<TSource>;
            if (list != null)
            {
                if (list.Count > 0)
                    return list[0];
            }
            else
            {
                using (IEnumerator<TSource> enumerator = source.GetEnumerator())
                {
                    if (enumerator.MoveNext())
                        return enumerator.Current;
                }
            }
            throw new InvalidOperationException("No elements is in the source.");
        }

        /// <summary>Returns the first element in a sequence that satisfies a specified condition.</summary>
        /// <returns>The first element in the sequence that passes the test in the specified predicate function.</returns>
        /// <param name="source">An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> to return an element from.</param>
        /// <param name="predicate">A function to test each element for a condition.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> or <paramref name="predicate" /> is null.</exception>
        /// <exception cref="TValue:System.InvalidOperationException">No element satisfies the condition in <paramref name="predicate" />.-or-The source sequence is empty.</exception>
        public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        //************************************if you get a compiler error here:************/
        //if you're using .net 3.5 or later : add a reference to "System.Core.dll"
        //if you're using .net 3.0 or 2.0 : modify the header of this file to tell compiler about this
        {
            if (source == null)
                throw new ArgumentNullException("source");

            if (predicate == null)
                throw new ArgumentNullException("predicate");

            foreach (TSource local in source)
            {
                if (predicate(local))
                    return local;
            }
            throw new InvalidOperationException("No matched element found in source.");
        }

        /// <summary>Returns the first element of a sequence, or a default value if the sequence contains no elements.</summary>
        /// <returns>default(<paramref name="TSource" />) if <paramref name="source" /> is empty; otherwise, the first element in <paramref name="source" />.</returns>
        /// <param name="source">The <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> to return the first element of.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> is null.</exception>
        public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            IList<TSource> list = source as IList<TSource>;
            if (list != null)
            {
                if (list.Count > 0)
                {
                    return list[0];
                }
            }
            else
            {
                using (IEnumerator<TSource> enumerator = source.GetEnumerator())
                {
                    if (enumerator.MoveNext())
                    {
                        return enumerator.Current;
                    }
                }
            }
            return default(TSource);
        }

        /// <summary>Returns the first element of the sequence that satisfies a condition or a default value if no such element is found.</summary>
        /// <returns>default(<paramref name="TSource" />) if <paramref name="source" /> is empty or if no element passes the test specified by <paramref name="predicate" />; otherwise, the first element in <paramref name="source" /> that passes the test specified by <paramref name="predicate" />.</returns>
        /// <param name="source">An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> to return an element from.</param>
        /// <param name="predicate">A function to test each element for a condition.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> or <paramref name="predicate" /> is null.</exception>
        public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (predicate == null)
            {
                throw new ArgumentNullException("predicate");
            }
            foreach (TSource local in source)
            {
                if (predicate(local))
                {
                    return local;
                }
            }
            return default(TSource);
        }

        /// <summary>Returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence.</summary>
        /// <returns>The single element of the input sequence.</returns>
        /// <param name="source">An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> to return the single element of.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> is null.</exception>
        /// <exception cref="TValue:System.InvalidOperationException">The input sequence contains more than one element.-or-The input sequence is empty.</exception>
        public static TSource Single<TSource>(this IEnumerable<TSource> source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            IList<TSource> list = source as IList<TSource>;
            if (list != null)
            {
                switch (list.Count)
                {
                    case 0:
                        throw new InvalidOperationException("No elements found in source.");

                    case 1:
                        return list[0];
                }
            }
            else
            {
                using (IEnumerator<TSource> enumerator = source.GetEnumerator())
                {
                    if (!enumerator.MoveNext())
                    {
                        throw new InvalidOperationException("No elements found in source.");
                    }
                    TSource current = enumerator.Current;
                    if (!enumerator.MoveNext())
                    {
                        return current;
                    }
                }
            }
            throw new InvalidOperationException("More than 1 elements found in source.");
        }

        /// <summary>Returns the only element of a sequence that satisfies a specified condition, and throws an exception if more than one such element exists.</summary>
        /// <returns>The single element of the input sequence that satisfies a condition.</returns>
        /// <param name="source">An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> to return a single element from.</param>
        /// <param name="predicate">A function to test an element for a condition.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> or <paramref name="predicate" /> is null.</exception>
        /// <exception cref="TValue:System.InvalidOperationException">No element satisfies the condition in <paramref name="predicate" />.-or-More than one element satisfies the condition in <paramref name="predicate" />.-or-The source sequence is empty.</exception>
        public static TSource Single<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (predicate == null)
            {
                throw new ArgumentNullException("predicate");
            }
            TSource local = default(TSource);
            long num = 0L;
            foreach (TSource local2 in source)
            {
                if (predicate(local2))
                {
                    local = local2;
                    num += 1L;
                }
            }
            long num2 = num;
            if ((num2 <= 1L) && (num2 >= 0L))
            {
                switch (((int)num2))
                {
                    case 0:
                        throw new InvalidOperationException("No matched elements found in source.");

                    case 1:
                        return local;
                }
            }
            throw new InvalidOperationException("More than 1 matched elements found in source.");
        }

        /// <summary>Returns the only element of a sequence, or a default value if the sequence is empty; this method throws an exception if there is more than one element in the sequence.</summary>
        /// <returns>The single element of the input sequence, or default(<paramref name="TSource" />) if the sequence contains no elements.</returns>
        /// <param name="source">An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> to return the single element of.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> is null.</exception>
        /// <exception cref="TValue:System.InvalidOperationException">The input sequence contains more than one element.</exception>
        public static TSource SingleOrDefault<TSource>(this IEnumerable<TSource> source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            IList<TSource> list = source as IList<TSource>;
            if (list != null)
            {
                switch (list.Count)
                {
                    case 0:
                        return default(TSource);

                    case 1:
                        return list[0];
                }
            }
            else
            {
                using (IEnumerator<TSource> enumerator = source.GetEnumerator())
                {
                    if (!enumerator.MoveNext())
                    {
                        return default(TSource);
                    }
                    TSource current = enumerator.Current;
                    if (!enumerator.MoveNext())
                    {
                        return current;
                    }
                }
            }
            throw new InvalidOperationException("More than 1 elements found in source.");
        }

        /// <summary>Returns the only element of a sequence that satisfies a specified condition or a default value if no such element exists; this method throws an exception if more than one element satisfies the condition.</summary>
        /// <returns>The single element of the input sequence that satisfies the condition, or default(<paramref name="TSource" />) if no such element is found.</returns>
        /// <param name="source">An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> to return a single element from.</param>
        /// <param name="predicate">A function to test an element for a condition.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> or <paramref name="predicate" /> is null.</exception>
        /// <exception cref="TValue:System.InvalidOperationException">More than one element satisfies the condition in <paramref name="predicate" />.</exception>
        public static TSource SingleOrDefault<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (predicate == null)
            {
                throw new ArgumentNullException("predicate");
            }
            TSource local = default(TSource);
            long num = 0L;
            foreach (TSource local2 in source)
            {
                if (predicate(local2))
                {
                    local = local2;
                    num += 1L;
                }
            }
            long num2 = num;
            if ((num2 <= 1L) && (num2 >= 0L))
            {
                switch (((int)num2))
                {
                    case 0:
                        return default(TSource);

                    case 1:
                        return local;
                }
            }
            throw new InvalidOperationException("More than 1 matched elements found in source.");
        }

        /// <summary>Projects each element of a sequence into a new form.</summary>
        /// <returns>An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> whose elements are the result of invoking the transform function on each element of <paramref name="source" />.</returns>
        /// <param name="source">A sequence of values to invoke a transform function on.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <typeparam name="TResult">The pluginType of the value returned by <paramref name="selector" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> or <paramref name="selector" /> is null.</exception>
        public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (selector == null)
                throw new ArgumentNullException("selector");

            return SelectIterator<TSource, TResult>(source, selector);
        }

        /// <summary>Projects each element of a sequence to an <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> and flattens the resulting sequences into one sequence.</summary>
        /// <returns>An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> whose elements are the result of invoking the one-to-many transform function on each element of the input sequence.</returns>
        /// <param name="source">A sequence of values to project.</param>
        /// <param name="selector">A transform function to apply to each element.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <typeparam name="TResult">The pluginType of the elements of the sequence returned by <paramref name="selector" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> or <paramref name="selector" /> is null.</exception>
        public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (selector == null)
            {
                throw new ArgumentNullException("selector");
            }
            return SelectManyIterator<TSource, TResult>(source, selector);
        }
        #endregion

        #region filter
        /// <summary>Filters a sequence of values based on a predicate.</summary>
        /// <returns>An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> that contains elements from the input sequence that satisfy the condition.</returns>
        /// <param name="source">An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> to filter.</param>
        /// <param name="predicate">A function to test each element for a condition.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> or <paramref name="predicate" /> is null.</exception>
        public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (predicate == null)
            {
                throw new ArgumentNullException("predicate");
            }
            return WhereIterator<TSource>(source, predicate);
        }

        /// <summary>Returns distinct elements from a sequence by using the default equality comparer to compare values.</summary>
        /// <returns>An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> that contains distinct elements from the source sequence.</returns>
        /// <param name="source">The sequence to remove duplicate elements from.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> is null.</exception>
        public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            return DistinctIterator<TSource>(source, null);
        }

        /// <summary>Returns distinct elements from a sequence by using a specified <see cref="TValue:System.Collections.Generic.IEqualityComparer`1" /> to compare values.</summary>
        /// <returns>An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> that contains distinct elements from the source sequence.</returns>
        /// <param name="source">The sequence to remove duplicate elements from.</param>
        /// <param name="comparer">An <see cref="TValue:System.Collections.Generic.IEqualityComparer`1" /> to compare values.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> is null.</exception>
        public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            return DistinctIterator<TSource>(source, comparer);
        }

        /// <summary>Produces the set difference of two sequences by using the default equality comparer to compare values.</summary>
        /// <returns>A sequence that contains the set difference of the elements of two sequences.</returns>
        /// <param name="first">An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> whose elements that are not also in <paramref name="second" /> will be returned.</param>
        /// <param name="second">An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> whose elements that also occur in the first sequence will cause those elements to be removed from the returned sequence.</param>
        /// <typeparam name="TSource">The pluginType of the elements of the input sequences.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="first" /> or <paramref name="second" /> is null.</exception>
        public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
        {
            if (first == null)
            {
                throw new ArgumentNullException("first");
            }
            if (second == null)
            {
                throw new ArgumentNullException("second");
            }
            return ExceptIterator<TSource>(first, second, null);
        }

        /// <summary>Produces the set union of two sequences by using the default equality comparer.</summary>
        /// <returns>An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> that contains the elements from both input sequences, excluding duplicates.</returns>
        /// <param name="first">An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> whose distinct elements form the first set for the union.</param>
        /// <param name="second">An <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> whose distinct elements form the second set for the union.</param>
        /// <typeparam name="TSource">The pluginType of the elements of the input sequences.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="first" /> or <paramref name="second" /> is null.</exception>
        public static IEnumerable<TSource> Union<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
        {
            if (first == null)
            {
                throw new ArgumentNullException("first");
            }
            if (second == null)
            {
                throw new ArgumentNullException("second");
            }
            return UnionIterator<TSource>(first, second, null);
        }
        #endregion

        #region actions
        /// <summary>
        /// Execute an action for each element in the collection
        /// </summary>
        /// <param name="source">The <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> to create a <see cref="TValue:System.Collections.Generic.List`1" /> from.</param>
        /// <param name="action">The <see cref="TValue:Sysetm.Action`1" /> to execute on every element.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> or <paramref name="action"/> is null.</exception>
        public static void ForEach<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
        {
            if (source == null)
                throw new ArgumentNullException("source");
            if (action == null)
                throw new ArgumentNullException("action");

            foreach (TSource item in source)
                action(item);
        }

        /// <summary>Creates a <see cref="TValue:System.Collections.Generic.List`1" /> from an <see cref="TValue:System.Collections.Generic.IEnumerable`1" />.</summary>
        /// <returns>A <see cref="TValue:System.Collections.Generic.List`1" /> that contains elements from the input sequence.</returns>
        /// <param name="source">The <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> to create a <see cref="TValue:System.Collections.Generic.List`1" /> from.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> is null.</exception>
        public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            return new List<TSource>(source);
        }

        /// <summary>Creates a Array from an <see cref="TValue:System.Collections.Generic.IEnumerable`1" />.</summary>
        /// <returns>A <see cref="TValue:System.Collections.Generic.List`1" /> that contains elements from the input sequence.</returns>
        /// <param name="source">The <see cref="TValue:System.Collections.Generic.IEnumerable`1" /> to create a <see cref="TValue:System.Collections.Generic.List`1" /> from.</param>
        /// <typeparam name="TSource">The pluginType of the elements of <paramref name="source" />.</typeparam>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="source" /> is null.</exception>
        public static TSource[] ToArray<TSource>(this IEnumerable<TSource> source)
        {
            return source.ToList().ToArray();
        }
        #endregion

        #region implementions
        private static IEnumerable<TResult> SelectIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, TResult> selector)
        {
            foreach (TSource item in source)
            {
                yield return selector(item);
            }
        }

        private static IEnumerable<TSource> WhereIterator<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate)
        {
            foreach (TSource item in source)
            {
                if (predicate(item))
                    yield return item;
            }
        }

        private static IEnumerable<TResult> SelectManyIterator<TSource, TResult>(IEnumerable<TSource> source, Func<TSource, IEnumerable<TResult>> selector)
        {
            foreach (TSource item in source)
                foreach (TResult r in selector(item))
                    yield return r;
        }

        private static IEnumerable<TSource> ExceptIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
        {
            var set = new Set<TSource>(comparer);
            foreach (TSource local in second)
                set.Add(local);
            foreach (TSource item in first)
                if (set.Add(item))
                    yield return item;
        }

        private static IEnumerable<TSource> UnionIterator<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
        {
            var set = new Set<TSource>(comparer);

            foreach (TSource item in first)
                if (set.Add(item))
                    yield return item;

            foreach (TSource item in second)
                if (set.Add(item))
                    yield return item;
        }

        private static IEnumerable<TSource> DistinctIterator<TSource>(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
        {
            var set = new Set<TSource>(comparer);
            foreach (TSource item in source)
                if (set.Add(item))
                    yield return item;
        }
        #endregion
    }

    internal class Set<TElement>
    {
        private int[] buckets;
        private IEqualityComparer<TElement> comparer;
        private int count;
        private int freeList;
        private Slot<TElement>[] slots;

        public Set()
            : this(null)
        {
        }

        public Set(IEqualityComparer<TElement> comparer)
        {
            if (comparer == null)
            {
                comparer = EqualityComparer<TElement>.Default;
            }
            this.comparer = comparer;
            this.buckets = new int[7];
            this.slots = new Slot<TElement>[7];
            this.freeList = -1;
        }

        public bool Add(TElement value)
        {
            return !this.Find(value, true);
        }

        public bool Contains(TElement value)
        {
            return this.Find(value, false);
        }

        private bool Find(TElement value, bool add)
        {
            int num = this.comparer.GetHashCode(value) & 0x7fffffff;
            for (int i = this.buckets[num % this.buckets.Length] - 1; i >= 0; i = this.slots[i].next)
            {
                if ((this.slots[i].hashCode == num) && this.comparer.Equals(this.slots[i].value, value))
                {
                    return true;
                }
            }
            if (add)
            {
                int freeList;
                if (this.freeList >= 0)
                {
                    freeList = this.freeList;
                    this.freeList = this.slots[freeList].next;
                }
                else
                {
                    if (this.count == this.slots.Length)
                    {
                        this.Resize();
                    }
                    freeList = this.count;
                    this.count++;
                }
                int index = num % this.buckets.Length;
                this.slots[freeList].hashCode = num;
                this.slots[freeList].value = value;
                this.slots[freeList].next = this.buckets[index] - 1;
                this.buckets[index] = freeList + 1;
            }
            return false;
        }

        public bool Remove(TElement value)
        {
            int num = this.comparer.GetHashCode(value) & 0x7fffffff;
            int index = num % this.buckets.Length;
            int num3 = -1;
            for (int i = this.buckets[index] - 1; i >= 0; i = this.slots[i].next)
            {
                if ((this.slots[i].hashCode == num) && this.comparer.Equals(this.slots[i].value, value))
                {
                    if (num3 < 0)
                    {
                        this.buckets[index] = this.slots[i].next + 1;
                    }
                    else
                    {
                        this.slots[num3].next = this.slots[i].next;
                    }
                    this.slots[i].hashCode = -1;
                    this.slots[i].value = default(TElement);
                    this.slots[i].next = this.freeList;
                    this.freeList = i;
                    return true;
                }
                num3 = i;
            }
            return false;
        }

        private void Resize()
        {
            int num = (this.count * 2) + 1;
            int[] numArray = new int[num];
            Slot<TElement>[] destinationArray = new Slot<TElement>[num];
            Array.Copy(this.slots, 0, destinationArray, 0, this.count);
            for (int i = 0; i < this.count; i++)
            {
                int index = destinationArray[i].hashCode % num;
                destinationArray[i].next = numArray[index] - 1;
                numArray[index] = i + 1;
            }
            this.buckets = numArray;
            this.slots = destinationArray;
        }

        internal struct Slot<TItem>
        {
            internal int hashCode;
            internal TItem value;
            internal int next;
        }
    }

}

namespace System
{
    public delegate TResult Func<T, TResult>(T arg);
}

namespace System.Collections.Generic
{
    /// <summary>Represents a set of values.</summary>
    [Serializable]
    public class HashSet<T> : ICollection<T>, IEnumerable<T>, IEnumerable, ISerializable, IDeserializationCallback
    {
        private const string CapacityName = "Capacity";
        private const string ComparerName = "Comparer";
        private const string ElementsName = "Elements";
        private const int GrowthFactor = 2;
        private const int Lower31BitMask = 0x7fffffff;
        private int[] m_buckets;
        private IEqualityComparer<T> m_comparer;
        private int m_count;
        private int m_freeList;
        private int m_lastIndex;
        private SerializationInfo m_siInfo;
        private Slot<T>[] m_slots;
        private int m_version;
        private const int ShrinkThreshold = 3;
        private const int StackAllocThreshold = 100;
        private const string VersionName = "Version";

        /// <summary>Initializes a new instance of the <see cref="TValue:System.Collections.Generic.HashSet`1" /> class that is empty and uses the default equality comparer for the set pluginType.</summary>
        public HashSet()
            : this(EqualityComparer<T>.Default)
        {
        }

        /// <summary>Initializes a new instance of the <see cref="TValue:System.Collections.Generic.HashSet`1" /> class that uses the default equality comparer for the set pluginType, contains elements copied from the specified collection, and has sufficient capacity to accommodate the number of elements copied.</summary>
        /// <param name="collection">The collection whose elements are copied to the new set.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="collection" /> is null.</exception>
        public HashSet(IEnumerable<T> collection)
            : this(collection, EqualityComparer<T>.Default)
        {
        }

        /// <summary>Initializes a new instance of the <see cref="TValue:System.Collections.Generic.HashSet`1" /> class that is empty and uses the specified equality comparer for the set pluginType.</summary>
        /// <param name="comparer">The <see cref="TValue:System.Collections.Generic.IEqualityComparer`1" /> implementation to use when comparing values in the set, or null to use the default <see cref="TValue:System.Collections.Generic.EqualityComparer`1" /> implementation for the set pluginType.</param>
        public HashSet(IEqualityComparer<T> comparer)
        {
            if (comparer == null)
            {
                comparer = EqualityComparer<T>.Default;
            }
            this.m_comparer = comparer;
            this.m_lastIndex = 0;
            this.m_count = 0;
            this.m_freeList = -1;
            this.m_version = 0;
        }

        /// <summary>Initializes a new instance of the <see cref="TValue:System.Collections.Generic.HashSet`1" /> class that uses the specified equality comparer for the set pluginType, contains elements copied from the specified collection, and has sufficient capacity to accommodate the number of elements copied.</summary>
        /// <param name="collection">The collection whose elements are copied to the new set.</param>
        /// <param name="comparer">The <see cref="TValue:System.Collections.Generic.IEqualityComparer`1" /> implementation to use when comparing values in the set, or null to use the default <see cref="TValue:System.Collections.Generic.EqualityComparer`1" /> implementation for the set pluginType.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="collection" /> is null.</exception>
        public HashSet(IEnumerable<T> collection, IEqualityComparer<T> comparer)
            : this(comparer)
        {
            if (collection == null)
            {
                throw new ArgumentNullException("collection");
            }
            int capacity = 0;
            ICollection<T> is2 = collection as ICollection<T>;
            if (is2 != null)
            {
                capacity = is2.Count;
            }
            this.Initialize(capacity);
            this.UnionWith(collection);
            if (((this.m_count == 0) && (this.m_slots.Length > HashHelpers.GetMinPrime())) || ((this.m_count > 0) && ((this.m_slots.Length / this.m_count) > 3)))
            {
                this.TrimExcess();
            }
        }

        /// <summary>Initializes a new instance of the <see cref="TValue:System.Collections.Generic.HashSet`1" /> class with serialized data.</summary>
        /// <param name="signature">A <see cref="TValue:System.Runtime.Serialization.SerializationInfo" /> object that contains the information required to serialize the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</param>
        /// <param name="dependencies">A <see cref="TValue:System.Runtime.Serialization.StreamingContext" /> structure that contains the source and destination of the serialized stream associated with the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</param>
        protected HashSet(SerializationInfo info, StreamingContext context)
        {
            this.m_siInfo = info;
        }

        /// <summary>Adds the specified element to a set.</summary>
        /// <returns>true if the element is added to the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object; false if the element is already present.</returns>
        /// <param name="item">The element to add to the set.</param>
        public bool Add(T item)
        {
            return this.AddIfNotPresent(item);
        }

        private bool AddIfNotPresent(T value)
        {
            int freeList;
            if (this.m_buckets == null)
            {
                this.Initialize(0);
            }
            int num = this.m_comparer.GetHashCode(value) & 0x7fffffff;
            int index = num % this.m_buckets.Length;
            for (int i = this.m_buckets[num % this.m_buckets.Length] - 1; i >= 0; i = this.m_slots[i].next)
            {
                if ((this.m_slots[i].hashCode == num) && this.m_comparer.Equals(this.m_slots[i].value, value))
                {
                    return false;
                }
            }
            if (this.m_freeList >= 0)
            {
                freeList = this.m_freeList;
                this.m_freeList = this.m_slots[freeList].next;
            }
            else
            {
                if (this.m_lastIndex == this.m_slots.Length)
                {
                    this.IncreaseCapacity();
                    index = num % this.m_buckets.Length;
                }
                freeList = this.m_lastIndex;
                this.m_lastIndex++;
            }
            this.m_slots[freeList].hashCode = num;
            this.m_slots[freeList].value = value;
            this.m_slots[freeList].next = this.m_buckets[index] - 1;
            this.m_buckets[index] = freeList + 1;
            this.m_count++;
            this.m_version++;
            return true;
        }

        private bool AddOrGetLocation(T value, out int location)
        {
            int freeList;
            int num = this.m_comparer.GetHashCode(value) & 0x7fffffff;
            int index = num % this.m_buckets.Length;
            for (int i = this.m_buckets[num % this.m_buckets.Length] - 1; i >= 0; i = this.m_slots[i].next)
            {
                if ((this.m_slots[i].hashCode == num) && this.m_comparer.Equals(this.m_slots[i].value, value))
                {
                    location = i;
                    return false;
                }
            }
            if (this.m_freeList >= 0)
            {
                freeList = this.m_freeList;
                this.m_freeList = this.m_slots[freeList].next;
            }
            else
            {
                if (this.m_lastIndex == this.m_slots.Length)
                {
                    this.IncreaseCapacity();
                    index = num % this.m_buckets.Length;
                }
                freeList = this.m_lastIndex;
                this.m_lastIndex++;
            }
            this.m_slots[freeList].hashCode = num;
            this.m_slots[freeList].value = value;
            this.m_slots[freeList].next = this.m_buckets[index] - 1;
            this.m_buckets[index] = freeList + 1;
            this.m_count++;
            this.m_version++;
            location = freeList;
            return true;
        }

        private static bool AreEqualityComparersEqual(HashSet<T> set1, HashSet<T> set2)
        {
            return set1.Comparer.Equals(set2.Comparer);
        }

        private unsafe ElementCount<T> CheckUniqueAndUnfoundElements(IEnumerable<T> other, bool returnIfUnfound)
        {
            ElementCount<T> count;
            if (this.m_count != 0)
            {
                BitHelper helper;
                int length = BitHelper.ToIntArrayLength(this.m_lastIndex);
                if (length <= 100)
                {
                    int* bitArrayPtr = stackalloc int[length];
                    helper = new BitHelper(bitArrayPtr, length);
                }
                else
                {
                    int[] bitArray = new int[length];
                    helper = new BitHelper(bitArray, length);
                }
                int num4 = 0;
                int num5 = 0;
                foreach (T local in other)
                {
                    int bitPosition = this.InternalIndexOf(local);
                    if (bitPosition >= 0)
                    {
                        if (!helper.IsMarked(bitPosition))
                        {
                            helper.MarkBit(bitPosition);
                            num5++;
                        }
                        continue;
                    }
                    num4++;
                    if (returnIfUnfound)
                    {
                        break;
                    }
                }
                count.uniqueCount = num5;
                count.unfoundCount = num4;
                return count;
            }
            int num = 0;
            using (IEnumerator<T> enumerator = other.GetEnumerator())
            {
                while (enumerator.MoveNext())
                {
                    T current = enumerator.Current;
                    num++;
                    goto Label_0039;
                }
            }
        Label_0039:
            count.uniqueCount = 0;
            count.unfoundCount = num;
            return count;
        }

        /// <summary>Removes enabledActavitors elements from a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</summary>
        public void Clear()
        {
            if (this.m_lastIndex > 0)
            {
                Array.Clear(this.m_slots, 0, this.m_lastIndex);
                Array.Clear(this.m_buckets, 0, this.m_buckets.Length);
                this.m_lastIndex = 0;
                this.m_count = 0;
                this.m_freeList = -1;
            }
            this.m_version++;
        }

        /// <summary>Determines whether a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object contains the specified element.</summary>
        /// <returns>true if the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object contains the specified element; otherwise, false.</returns>
        /// <param name="item">The element to locate in the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</param>
        public bool Contains(T item)
        {
            if (this.m_buckets != null)
            {
                int num = this.m_comparer.GetHashCode(item) & 0x7fffffff;
                for (int i = this.m_buckets[num % this.m_buckets.Length] - 1; i >= 0; i = this.m_slots[i].next)
                {
                    if ((this.m_slots[i].hashCode == num) && this.m_comparer.Equals(this.m_slots[i].value, item))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        private bool ContainsAllElements(IEnumerable<T> other)
        {
            foreach (T local in other)
            {
                if (!this.Contains(local))
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>Copies the elements of a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object to an array.</summary>
        /// <param name="array">The one-dimensional array that is the destination of the elements copied from the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object. The array must have zero-based indexing.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="array" /> is null.</exception>
        public void CopyTo(T[] array)
        {
            this.CopyTo(array, 0, this.m_count);
        }

        /// <summary>Copies the elements of a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object to an array, starting at the specified array index.</summary>
        /// <param name="array">The one-dimensional array that is the destination of the elements copied from the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object. The array must have zero-based indexing.</param>
        /// <param name="arrayIndex">The zero-based index in <paramref name="array" /> at which copying begins.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="array" /> is null.</exception>
        /// <exception cref="TValue:System.ArgumentOutOfRangeException">
        /// <paramref name="arrayIndex" /> is less than 0.</exception>
        /// <exception cref="TValue:System.ArgumentException">
        /// <paramref name="arrayIndex" /> is greater than the length of the destination <paramref name="array" />.-or-<paramref name="count" /> is larger than the size of the destination <paramref name="array" />.</exception>
        public void CopyTo(T[] array, int arrayIndex)
        {
            this.CopyTo(array, arrayIndex, this.m_count);
        }

        /// <summary>Copies the specified number of elements of a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object to an array, starting at the specified array index.</summary>
        /// <param name="array">The one-dimensional array that is the destination of the elements copied from the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object. The array must have zero-based indexing.</param>
        /// <param name="arrayIndex">The zero-based index in <paramref name="array" /> at which copying begins.</param>
        /// <param name="count">The number of elements to copy to <paramref name="array" />.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="array" /> is null.</exception>
        /// <exception cref="TValue:System.ArgumentOutOfRangeException">
        /// <paramref name="arrayIndex" /> is less than 0.-or-<paramref name="count" /> is less than 0.</exception>
        /// <exception cref="TValue:System.ArgumentException">
        /// <paramref name="arrayIndex" /> is greater than the length of the destination <paramref name="array" />.-or-<paramref name="count" /> is greater than the available space from the <paramref name="index" /> to the end of the destination <paramref name="array" />.</exception>
        public void CopyTo(T[] array, int arrayIndex, int count)
        {
            if (array == null)
            {
                throw new ArgumentNullException("array");
            }
            if (arrayIndex < 0)
            {
                throw new ArgumentOutOfRangeException("arrayIndex", "ArgumentOutOfRange_NeedNonNegNum");
            }
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException("count", "ArgumentOutOfRange_NeedNonNegNum");
            }
            if ((arrayIndex > array.Length) || (count > (array.Length - arrayIndex)))
            {
                throw new ArgumentException("Arg_ArrayPlusOffTooSmall");
            }
            int num = 0;
            for (int i = 0; (i < this.m_lastIndex) && (num < count); i++)
            {
                if (this.m_slots[i].hashCode >= 0)
                {
                    array[arrayIndex + num] = this.m_slots[i].value;
                    num++;
                }
            }
        }

        /// <summary>Returns an <see cref="TValue:System.Collections.IEqualityComparer" /> object that can be used for deep equality testing of a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</summary>
        /// <returns>An <see cref="TValue:System.Collections.IEqualityComparer" /> object that can be used for deep equality testing of the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</returns>
        public static IEqualityComparer<HashSet<T>> CreateSetComparer()
        {
            return new HashSetEqualityComparer<T>();
        }

        /// <summary>Removes enabledActavitors elements in the specified collection from the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</summary>
        /// <param name="other">The collection of items to remove from the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="other" /> is null.</exception>
        public void ExceptWith(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (this.m_count != 0)
            {
                if (other == this)
                {
                    this.Clear();
                }
                else
                {
                    foreach (T local in other)
                    {
                        this.Remove(local);
                    }
                }
            }
        }

        /// <summary>Returns an enumerator that iterates through a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</summary>
        /// <returns>A <see cref="TValue:System.Collections.Generic.HashSet`1.Enumerator" /> object for the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</returns>
        public Enumerator<T> GetEnumerator()
        {
            return new Enumerator<T>((HashSet<T>)this);
        }

        /// <summary>Implements the <see cref="TValue:System.Runtime.Serialization.ISerializable" /> interface and returns the data needed to serialize a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</summary>
        /// <param name="signature">A <see cref="TValue:System.Runtime.Serialization.SerializationInfo" /> object that contains the information required to serialize the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</param>
        /// <param name="dependencies">A <see cref="TValue:System.Runtime.Serialization.StreamingContext" /> structure that contains the source and destination of the serialized stream associated with the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="signature" /> is null.</exception>
        /// <filterpriority>2</filterpriority>
        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }
            info.AddValue("Version", this.m_version);
            info.AddValue("Comparer", this.m_comparer, typeof(IEqualityComparer<T>));
            info.AddValue("Capacity", (this.m_buckets == null) ? 0 : this.m_buckets.Length);
            if (this.m_buckets != null)
            {
                T[] array = new T[this.m_count];
                this.CopyTo(array);
                info.AddValue("Elements", array, typeof(T[]));
            }
        }

        internal static bool HashSetEquals(HashSet<T> set1, HashSet<T> set2, IEqualityComparer<T> comparer)
        {
            if (set1 == null)
            {
                return (set2 == null);
            }
            if (set2 == null)
            {
                return false;
            }
            if (HashSet<T>.AreEqualityComparersEqual(set1, set2))
            {
                if (set1.Count != set2.Count)
                {
                    return false;
                }
                foreach (T local in set2)
                {
                    if (!set1.Contains(local))
                    {
                        return false;
                    }
                }
                return true;
            }
            foreach (T local2 in set2)
            {
                bool flag = false;
                foreach (T local3 in set1)
                {
                    if (comparer.Equals(local2, local3))
                    {
                        flag = true;
                        break;
                    }
                }
                if (!flag)
                {
                    return false;
                }
            }
            return true;
        }

        private void IncreaseCapacity()
        {
            int min = this.m_count * 2;
            if (min < 0)
            {
                min = this.m_count;
            }
            int prime = HashHelpers.GetPrime(min);
            if (prime <= this.m_count)
            {
                throw new ArgumentException("Arg_HSCapacityOverflow");
            }
            Slot<T>[] destinationArray = new Slot<T>[prime];
            if (this.m_slots != null)
            {
                Array.Copy(this.m_slots, 0, destinationArray, 0, this.m_lastIndex);
            }
            int[] numArray = new int[prime];
            for (int i = 0; i < this.m_lastIndex; i++)
            {
                int index = destinationArray[i].hashCode % prime;
                destinationArray[i].next = numArray[index] - 1;
                numArray[index] = i + 1;
            }
            this.m_slots = destinationArray;
            this.m_buckets = numArray;
        }

        private void Initialize(int capacity)
        {
            int prime = HashHelpers.GetPrime(capacity);
            this.m_buckets = new int[prime];
            this.m_slots = new Slot<T>[prime];
        }

        private int InternalIndexOf(T item)
        {
            int num = this.m_comparer.GetHashCode(item) & 0x7fffffff;
            for (int i = this.m_buckets[num % this.m_buckets.Length] - 1; i >= 0; i = this.m_slots[i].next)
            {
                if ((this.m_slots[i].hashCode == num) && this.m_comparer.Equals(this.m_slots[i].value, item))
                {
                    return i;
                }
            }
            return -1;
        }

        /// <summary>Modifies the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object to contain only elements that are present in that object and in the specified collection.</summary>
        /// <param name="other">The collection to compare to the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="other" /> is null.</exception>
        public void IntersectWith(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (this.m_count != 0)
            {
                ICollection<T> is2 = other as ICollection<T>;
                if (is2 != null)
                {
                    if (is2.Count == 0)
                    {
                        this.Clear();
                        return;
                    }
                    HashSet<T> set = other as HashSet<T>;
                    if ((set != null) && HashSet<T>.AreEqualityComparersEqual((HashSet<T>)this, set))
                    {
                        this.IntersectWithHashSetWithSameEC(set);
                        return;
                    }
                }
                this.IntersectWithEnumerable(other);
            }
        }

        private unsafe void IntersectWithEnumerable(IEnumerable<T> other)
        {
            BitHelper helper;
            int lastIndex = this.m_lastIndex;
            int length = BitHelper.ToIntArrayLength(lastIndex);
            if (length <= 100)
            {
                int* bitArrayPtr = stackalloc int[length];
                helper = new BitHelper(bitArrayPtr, length);
            }
            else
            {
                int[] bitArray = new int[length];
                helper = new BitHelper(bitArray, length);
            }
            foreach (T local in other)
            {
                int bitPosition = this.InternalIndexOf(local);
                if (bitPosition >= 0)
                {
                    helper.MarkBit(bitPosition);
                }
            }
            for (int i = 0; i < lastIndex; i++)
            {
                if ((this.m_slots[i].hashCode >= 0) && !helper.IsMarked(i))
                {
                    this.Remove(this.m_slots[i].value);
                }
            }
        }

        private void IntersectWithHashSetWithSameEC(HashSet<T> other)
        {
            for (int i = 0; i < this.m_lastIndex; i++)
            {
                if (this.m_slots[i].hashCode >= 0)
                {
                    T item = this.m_slots[i].value;
                    if (!other.Contains(item))
                    {
                        this.Remove(item);
                    }
                }
            }
        }

        /// <summary>Determines whether a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object is a proper subset of the specified collection.</summary>
        /// <returns>true if the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object is a proper subset of <paramref name="other" />; otherwise, false.</returns>
        /// <param name="other">The collection to compare to the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="other" /> is null.</exception>
        public bool IsProperSubsetOf(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            ICollection<T> is2 = other as ICollection<T>;
            if (is2 != null)
            {
                if (this.m_count == 0)
                {
                    return (is2.Count > 0);
                }
                HashSet<T> set = other as HashSet<T>;
                if ((set != null) && HashSet<T>.AreEqualityComparersEqual((HashSet<T>)this, set))
                {
                    if (this.m_count >= set.Count)
                    {
                        return false;
                    }
                    return this.IsSubsetOfHashSetWithSameEC(set);
                }
            }
            ElementCount<T> count = this.CheckUniqueAndUnfoundElements(other, false);
            return ((count.uniqueCount == this.m_count) && (count.unfoundCount > 0));
        }

        /// <summary>Determines whether a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object is a proper superset of the specified collection.</summary>
        /// <returns>true if the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object is a proper superset of <paramref name="other" />; otherwise, false.</returns>
        /// <param name="other">The collection to compare to the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object. </param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="other" /> is null.</exception>
        public bool IsProperSupersetOf(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (this.m_count == 0)
            {
                return false;
            }
            ICollection<T> is2 = other as ICollection<T>;
            if (is2 != null)
            {
                if (is2.Count == 0)
                {
                    return true;
                }
                HashSet<T> set = other as HashSet<T>;
                if ((set != null) && HashSet<T>.AreEqualityComparersEqual((HashSet<T>)this, set))
                {
                    if (set.Count >= this.m_count)
                    {
                        return false;
                    }
                    return this.ContainsAllElements(set);
                }
            }
            ElementCount<T> count = this.CheckUniqueAndUnfoundElements(other, true);
            return ((count.uniqueCount < this.m_count) && (count.unfoundCount == 0));
        }

        /// <summary>Determines whether a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object is a subset of the specified collection.</summary>
        /// <returns>true if the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object is a subset of <paramref name="other" />; otherwise, false.</returns>
        /// <param name="other">The collection to compare to the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="other" /> is null.</exception>
        public bool IsSubsetOf(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (this.m_count == 0)
            {
                return true;
            }
            HashSet<T> set = other as HashSet<T>;
            if ((set != null) && HashSet<T>.AreEqualityComparersEqual((HashSet<T>)this, set))
            {
                if (this.m_count > set.Count)
                {
                    return false;
                }
                return this.IsSubsetOfHashSetWithSameEC(set);
            }
            ElementCount<T> count = this.CheckUniqueAndUnfoundElements(other, false);
            return ((count.uniqueCount == this.m_count) && (count.unfoundCount >= 0));
        }

        private bool IsSubsetOfHashSetWithSameEC(HashSet<T> other)
        {
            foreach (T local in this)
            {
                if (!other.Contains(local))
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>Determines whether a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object is a superset of the specified collection.</summary>
        /// <returns>true if the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object is a superset of <paramref name="other" />; otherwise, false.</returns>
        /// <param name="other">The collection to compare to the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="other" /> is null.</exception>
        public bool IsSupersetOf(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            ICollection<T> is2 = other as ICollection<T>;
            if (is2 != null)
            {
                if (is2.Count == 0)
                {
                    return true;
                }
                HashSet<T> set = other as HashSet<T>;
                if (((set != null) && HashSet<T>.AreEqualityComparersEqual((HashSet<T>)this, set)) && (set.Count > this.m_count))
                {
                    return false;
                }
            }
            return this.ContainsAllElements(other);
        }

        /// <summary>Implements the <see cref="TValue:System.Runtime.Serialization.ISerializable" /> interface and raises the deserialization event when the deserialization is complete.</summary>
        /// <param name="sender">The source of the deserialization event.</param>
        /// <exception cref="TValue:System.Runtime.Serialization.SerializationException">The <see cref="TValue:System.Runtime.Serialization.SerializationInfo" /> object associated with the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object is invalid.</exception>
        /// <filterpriority>2</filterpriority>
        public virtual void OnDeserialization(object sender)
        {
            if (this.m_siInfo != null)
            {
                int num = this.m_siInfo.GetInt32("Capacity");
                this.m_comparer = (IEqualityComparer<T>)this.m_siInfo.GetValue("Comparer", typeof(IEqualityComparer<T>));
                if (num != 0)
                {
                    this.m_buckets = new int[num];
                    this.m_slots = new Slot<T>[num];
                    this.m_freeList = -1;
                    T[] localArray = (T[])this.m_siInfo.GetValue("Elements", typeof(T[]));
                    if (localArray == null)
                    {
                        throw new SerializationException("Serialization_MissingKeys");
                    }
                    for (int i = 0; i < localArray.Length; i++)
                    {
                        this.AddIfNotPresent(localArray[i]);
                    }
                }
                else
                {
                    this.m_buckets = null;
                }
                this.m_version = this.m_siInfo.GetInt32("Version");
                this.m_siInfo = null;
            }
        }

        /// <summary>Determines whether the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object overlaps the specified collection.</summary>
        /// <returns>true if the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object and <paramref name="other" /> share at least one common element; otherwise, false.</returns>
        /// <param name="other">The collection to compare to the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="other" /> is null.</exception>
        public bool Overlaps(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (this.m_count != 0)
            {
                foreach (T local in other)
                {
                    if (this.Contains(local))
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>Removes the specified element from a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</summary>
        /// <returns>true if the element is successfully found and removed; otherwise, false.  This method returns false if <paramref name="item" /> is not found in the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</returns>
        /// <param name="item">The element to remove.</param>
        public bool Remove(T item)
        {
            if (this.m_buckets != null)
            {
                int num = this.m_comparer.GetHashCode(item) & 0x7fffffff;
                int index = num % this.m_buckets.Length;
                int num3 = -1;
                for (int i = this.m_buckets[index] - 1; i >= 0; i = this.m_slots[i].next)
                {
                    if ((this.m_slots[i].hashCode == num) && this.m_comparer.Equals(this.m_slots[i].value, item))
                    {
                        if (num3 < 0)
                        {
                            this.m_buckets[index] = this.m_slots[i].next + 1;
                        }
                        else
                        {
                            this.m_slots[num3].next = this.m_slots[i].next;
                        }
                        this.m_slots[i].hashCode = -1;
                        this.m_slots[i].value = default(T);
                        this.m_slots[i].next = this.m_freeList;
                        this.m_freeList = i;
                        this.m_count--;
                        this.m_version++;
                        return true;
                    }
                    num3 = i;
                }
            }
            return false;
        }

        /// <summary>Removes enabledActavitors elements that match the conditions defined by the specified predicate from a <see cref="TValue:System.Collections.Generic.HashSet`1" /> collection.</summary>
        /// <returns>The number of elements that were removed from the <see cref="TValue:System.Collections.Generic.HashSet`1" /> collection.</returns>
        /// <param name="match">The <see cref="TValue:System.Predicate`1" /> delegate that defines the conditions of the elements to remove.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="match" /> is null.</exception>
        public int RemoveWhere(Predicate<T> match)
        {
            if (match == null)
            {
                throw new ArgumentNullException("match");
            }
            int num = 0;
            for (int i = 0; i < this.m_lastIndex; i++)
            {
                if (this.m_slots[i].hashCode >= 0)
                {
                    T local = this.m_slots[i].value;
                    if (match(local) && this.Remove(local))
                    {
                        num++;
                    }
                }
            }
            return num;
        }

        /// <summary>Determines whether a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object and the specified collection contain the same elements.</summary>
        /// <returns>true if the <see cref="TValue:System.Collections.Generic.HashSet`1" /> object is equal to <paramref name="other" />; otherwise, false.</returns>
        /// <param name="other">The collection to compare to the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="other" /> is null.</exception>
        public bool SetEquals(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            HashSet<T> set = other as HashSet<T>;
            if ((set != null) && HashSet<T>.AreEqualityComparersEqual((HashSet<T>)this, set))
            {
                if (this.m_count != set.Count)
                {
                    return false;
                }
                return this.ContainsAllElements(set);
            }
            ICollection<T> is2 = other as ICollection<T>;
            if (((is2 != null) && (this.m_count == 0)) && (is2.Count > 0))
            {
                return false;
            }
            ElementCount<T> count = this.CheckUniqueAndUnfoundElements(other, true);
            return ((count.uniqueCount == this.m_count) && (count.unfoundCount == 0));
        }

        /// <summary>Modifies the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object to contain only elements that are present either in that object or in the specified collection, but not both.</summary>
        /// <param name="other">The collection to compare to the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="other" /> is null.</exception>
        public void SymmetricExceptWith(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            if (this.m_count == 0)
            {
                this.UnionWith(other);
            }
            else if (other == this)
            {
                this.Clear();
            }
            else
            {
                HashSet<T> set = other as HashSet<T>;
                if ((set != null) && HashSet<T>.AreEqualityComparersEqual((HashSet<T>)this, set))
                {
                    this.SymmetricExceptWithUniqueHashSet(set);
                }
                else
                {
                    this.SymmetricExceptWithEnumerable(other);
                }
            }
        }

        private unsafe void SymmetricExceptWithEnumerable(IEnumerable<T> other)
        {
            BitHelper helper;
            BitHelper helper2;
            int lastIndex = this.m_lastIndex;
            int length = BitHelper.ToIntArrayLength(lastIndex);
            if (length <= 50)
            {
                int* bitArrayPtr = stackalloc int[length];
                helper = new BitHelper(bitArrayPtr, length);
                int* numPtr2 = stackalloc int[length];
                helper2 = new BitHelper(numPtr2, length);
            }
            else
            {
                int[] bitArray = new int[length];
                helper = new BitHelper(bitArray, length);
                int[] numArray2 = new int[length];
                helper2 = new BitHelper(numArray2, length);
            }
            foreach (T local in other)
            {
                int location = 0;
                if (this.AddOrGetLocation(local, out location))
                {
                    helper2.MarkBit(location);
                    continue;
                }
                if ((location < lastIndex) && !helper2.IsMarked(location))
                {
                    helper.MarkBit(location);
                }
            }
            for (int i = 0; i < lastIndex; i++)
            {
                if (helper.IsMarked(i))
                {
                    this.Remove(this.m_slots[i].value);
                }
            }
        }

        private void SymmetricExceptWithUniqueHashSet(HashSet<T> other)
        {
            foreach (T local in other)
            {
                if (!this.Remove(local))
                {
                    this.AddIfNotPresent(local);
                }
            }
        }

        void ICollection<T>.Add(T item)
        {
            this.AddIfNotPresent(item);
        }

        IEnumerator<T> IEnumerable<T>.GetEnumerator()
        {
            return new Enumerator<T>((HashSet<T>)this);
        }

        /// <summary>Returns an enumerator that iterates through a collection.</summary>
        /// <returns>An <see cref="TValue:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.</returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return new Enumerator<T>((HashSet<T>)this);
        }

        internal T[] ToArray()
        {
            T[] array = new T[this.Count];
            this.CopyTo(array);
            return array;
        }

        /// <summary>Sets the capacity of a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object to the actual number of elements it contains, rounded up to a nearby, implementation-specific value.</summary>
        public void TrimExcess()
        {
            if (this.m_count == 0)
            {
                this.m_buckets = null;
                this.m_slots = null;
                this.m_version++;
            }
            else
            {
                int prime = HashHelpers.GetPrime(this.m_count);
                Slot<T>[] slotArray = new Slot<T>[prime];
                int[] numArray = new int[prime];
                int index = 0;
                for (int i = 0; i < this.m_lastIndex; i++)
                {
                    if (this.m_slots[i].hashCode >= 0)
                    {
                        slotArray[index] = this.m_slots[i];
                        int num4 = slotArray[index].hashCode % prime;
                        slotArray[index].next = numArray[num4] - 1;
                        numArray[num4] = index + 1;
                        index++;
                    }
                }
                this.m_lastIndex = index;
                this.m_slots = slotArray;
                this.m_buckets = numArray;
                this.m_freeList = -1;
            }
        }

        /// <summary>Modifies the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object to contain enabledActavitors elements that are present in both itself and in the specified collection.</summary>
        /// <param name="other">The collection to compare to the current <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</param>
        /// <exception cref="TValue:System.ArgumentNullException">
        /// <paramref name="other" /> is null.</exception>
        public void UnionWith(IEnumerable<T> other)
        {
            if (other == null)
            {
                throw new ArgumentNullException("other");
            }
            foreach (T local in other)
            {
                this.AddIfNotPresent(local);
            }
        }

        /// <summary>Gets the <see cref="TValue:System.Collections.Generic.IEqualityComparer`1" /> object that is used to determine equality for the values in the set.</summary>
        /// <returns>The <see cref="TValue:System.Collections.Generic.IEqualityComparer`1" /> object that is used to determine equality for the values in the set.</returns>
        public IEqualityComparer<T> Comparer
        {
            get
            {
                return this.m_comparer;
            }
        }

        /// <summary>Gets the number of elements that are contained in a set.</summary>
        /// <returns>The number of elements that are contained in the set.</returns>
        public int Count
        {
            get
            {
                return this.m_count;
            }
        }

        bool ICollection<T>.IsReadOnly
        {
            get
            {
                return false;
            }
        }

        #region ElementCount
        internal struct ElementCount<TValue>
        {
            internal int uniqueCount;
            internal int unfoundCount;
        }
        #endregion

        #region Enumerator
        /// <summary>Enumerates the elements of a <see cref="TValue:System.Collections.Generic.HashSet`1" /> object.</summary>
        /// <filterpriority>2</filterpriority>
        [Serializable]
        public struct Enumerator<TValue> : IEnumerator<TValue>, IDisposable, IEnumerator
        {
            private HashSet<TValue> set;
            private int index;
            private int version;
            private TValue current;
            internal Enumerator(HashSet<TValue> set)
            {
                this.set = set;
                this.index = 0;
                this.version = set.m_version;
                this.current = default(TValue);
            }

            /// <summary>Releases enabledActavitors resources used by a <see cref="TValue:System.Collections.Generic.HashSet`1.Enumerator" /> object.</summary>
            public void Dispose()
            {
            }

            /// <summary>Advances the enumerator to the next element of the <see cref="TValue:System.Collections.Generic.HashSet`1" /> collection.</summary>
            /// <returns>true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.</returns>
            /// <exception cref="TValue:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception>
            public bool MoveNext()
            {
                if (this.version != this.set.m_version)
                {
                    throw new InvalidOperationException("InvalidOperation_EnumFailedVersion");
                }
                while (this.index < this.set.m_lastIndex)
                {
                    if (this.set.m_slots[this.index].hashCode >= 0)
                    {
                        this.current = this.set.m_slots[this.index].value;
                        this.index++;
                        return true;
                    }
                    this.index++;
                }
                this.index = this.set.m_lastIndex + 1;
                this.current = default(TValue);
                return false;
            }

            /// <summary>Gets the element at the current position of the enumerator.</summary>
            /// <returns>The element in the <see cref="TValue:System.Collections.Generic.HashSet`1" /> collection at the current position of the enumerator.</returns>
            public TValue Current
            {
                get
                {
                    return this.current;
                }
            }
            /// <summary>Gets the element at the current position of the enumerator.</summary>
            /// <returns>The element in the collection at the current position of the enumerator, as an <see cref="TValue:System.Object" />.</returns>
            /// <exception cref="TValue:System.InvalidOperationException">The enumerator is positioned before the first element of the collection or after the last element. </exception>
            object IEnumerator.Current
            {
                get
                {
                    if ((this.index == 0) || (this.index == (this.set.m_lastIndex + 1)))
                    {
                        throw new InvalidOperationException("InvalidOperation_EnumOpCantHappen");
                    }
                    return this.Current;
                }
            }
            /// <summary>Sets the enumerator to its initial position, which is before the first element in the collection.</summary>
            /// <exception cref="TValue:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception>
            void IEnumerator.Reset()
            {
                if (this.version != this.set.m_version)
                {
                    throw new InvalidOperationException("InvalidOperation_EnumFailedVersion");
                }
                this.index = 0;
                this.current = default(TValue);
            }
        }
        #endregion

        #region Slot
        internal struct Slot<TValue>
        {
            internal int hashCode;
            internal TValue value;
            internal int next;
        }
        #endregion

        #region HashHelpers
        internal static class HashHelpers
        {
            internal static readonly int[] primes = new int[] { 
        3, 7, 11, 0x11, 0x17, 0x1d, 0x25, 0x2f, 0x3b, 0x47, 0x59, 0x6b, 0x83, 0xa3, 0xc5, 0xef, 
        0x125, 0x161, 0x1af, 0x209, 0x277, 0x2f9, 0x397, 0x44f, 0x52f, 0x63d, 0x78b, 0x91d, 0xaf1, 0xd2b, 0xfd1, 0x12fd, 
        0x16cf, 0x1b65, 0x20e3, 0x2777, 0x2f6f, 0x38ff, 0x446f, 0x521f, 0x628d, 0x7655, 0x8e01, 0xaa6b, 0xcc89, 0xf583, 0x126a7, 0x1619b, 
        0x1a857, 0x1fd3b, 0x26315, 0x2dd67, 0x3701b, 0x42023, 0x4f361, 0x5f0ed, 0x72125, 0x88e31, 0xa443b, 0xc51eb, 0xec8c1, 0x11bdbf, 0x154a3f, 0x198c4f, 
        0x1ea867, 0x24ca19, 0x2c25c1, 0x34fa1b, 0x3f928f, 0x4c4987, 0x5b8b6f, 0x6dda89
     };

            internal static int GetMinPrime()
            {
                return primes[0];
            }

            internal static int GetPrime(int min)
            {
                for (int i = 0; i < primes.Length; i++)
                {
                    int num2 = primes[i];
                    if (num2 >= min)
                    {
                        return num2;
                    }
                }
                for (int j = min | 1; j < 0x7fffffff; j += 2)
                {
                    if (IsPrime(j))
                    {
                        return j;
                    }
                }
                return min;
            }

            internal static bool IsPrime(int candidate)
            {
                if ((candidate & 1) == 0)
                {
                    return (candidate == 2);
                }
                int num = (int)Math.Sqrt((double)candidate);
                for (int i = 3; i <= num; i += 2)
                {
                    if ((candidate % i) == 0)
                    {
                        return false;
                    }
                }
                return true;
            }
        }
        #endregion

        #region BitHelper
        internal class BitHelper
        {
            private const byte IntSize = 0x20;
            private int[] m_array;
            private unsafe int* m_arrayPtr;
            private int m_length;
            private const byte MarkedBitFlag = 1;
            private bool useStackAlloc;

            internal unsafe BitHelper(int* bitArrayPtr, int length)
            {
                this.m_arrayPtr = bitArrayPtr;
                this.m_length = length;
                this.useStackAlloc = true;
            }

            internal BitHelper(int[] bitArray, int length)
            {
                this.m_array = bitArray;
                this.m_length = length;
            }

            internal unsafe bool IsMarked(int bitPosition)
            {
                if (this.useStackAlloc)
                {
                    int num = bitPosition / 0x20;
                    return (((num < this.m_length) && (num >= 0)) && ((this.m_arrayPtr[num] & (((int)1) << (bitPosition % 0x20))) != 0));
                }
                int index = bitPosition / 0x20;
                return (((index < this.m_length) && (index >= 0)) && ((this.m_array[index] & (((int)1) << (bitPosition % 0x20))) != 0));
            }

            internal unsafe void MarkBit(int bitPosition)
            {
                if (this.useStackAlloc)
                {
                    int num = bitPosition / 0x20;
                    if ((num < this.m_length) && (num >= 0))
                    {
                        int* numPtr1 = this.m_arrayPtr + num;
                        numPtr1[0] |= ((int)1) << (bitPosition % 0x20);
                    }
                }
                else
                {
                    int index = bitPosition / 0x20;
                    if ((index < this.m_length) && (index >= 0))
                    {
                        this.m_array[index] |= ((int)1) << (bitPosition % 0x20);
                    }
                }
            }

            internal static int ToIntArrayLength(int n)
            {
                if (n <= 0)
                {
                    return 0;
                }
                return (((n - 1) / 0x20) + 1);
            }
        }
        #endregion

        #region HashSetEqualityComparer
        [Serializable]
        internal class HashSetEqualityComparer<TValue> : IEqualityComparer<HashSet<TValue>>
        {
            private IEqualityComparer<TValue> m_comparer;

            public HashSetEqualityComparer()
            {
                this.m_comparer = EqualityComparer<TValue>.Default;
            }

            public HashSetEqualityComparer(IEqualityComparer<TValue> comparer)
            {
                if (this.m_comparer == null)
                {
                    this.m_comparer = EqualityComparer<TValue>.Default;
                }
                else
                {
                    this.m_comparer = comparer;
                }
            }

            public override bool Equals(object obj)
            {
                HashSetEqualityComparer<TValue> comparer = obj as HashSetEqualityComparer<TValue>;
                if (comparer == null)
                {
                    return false;
                }
                return (this.m_comparer == comparer.m_comparer);
            }

            public bool Equals(HashSet<TValue> x, HashSet<TValue> y)
            {
                return HashSet<TValue>.HashSetEquals(x, y, this.m_comparer);
            }

            public override int GetHashCode()
            {
                return this.m_comparer.GetHashCode();
            }

            public int GetHashCode(HashSet<TValue> obj)
            {
                int num = 0;
                if (obj != null)
                {
                    foreach (TValue local in obj)
                    {
                        num ^= this.m_comparer.GetHashCode(local) & 0x7fffffff;
                    }
                }
                return num;
            }
        }
        #endregion

    }

}
#endif
